package com.qqt.csr.route.service;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.qqt.csr.common.utils.CacheKeyUtil;
import com.qqt.csr.common.utils.JsonUtil;
import com.qqt.csr.common.utils.RedissonLockUtil;
import com.qqt.csr.im.entity.Conversation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBatch;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RScoredSortedSetAsync;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Date;
import java.util.List;

@Slf4j
@Component
public class ConversationStatService {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RedissonLockUtil redissonLockUtil;
    @Autowired
    private RouteTaskService routeTaskService;

    /**
     * 记录每个业务规则每个技能组的会话时长
     *
     * @param conversation
     */
    public void increaseConversationTime(Conversation conversation) {
        if (conversation == null) {
            return;
        }
        JSONObject conversationExt = JsonUtil.toObject(conversation.getExt(), JSONObject.class);
        if (conversationExt == null) {
            return;
        }
        String tenantId = conversationExt.getString("tenantId");
        Long skillSetId = conversationExt.getLong("skillSetId");
        if (StringUtils.isBlank(tenantId) || skillSetId == null) {
            return;
        }

        Date currentTime = DateUtil.date();
        Date todayEndTime = DateUtil.endOfDay(currentTime);
        Date startTime = DateUtil.parseDateTime(conversation.getStartTime());
        Date endTime = new Date();
        long duration = endTime.getTime() - startTime.getTime();

        String cacheKey = String.format(CacheKeyUtil.CsrRoute.DISTRIBUTION_SKILL_SET_STAT_CONVERSATION_TIME, tenantId);
        RScoredSortedSet<Long> scoredSortedSet = redissonClient.getScoredSortedSet(cacheKey);
        scoredSortedSet.addScoreAsync(skillSetId, duration);
        scoredSortedSet.expireAsync(Duration.ofMillis(todayEndTime.getTime() - currentTime.getTime()));
    }

    /**
     * 记录每个业务规则每个技能组的会话时长
     *
     * @param conversationList
     */
    public void increaseConversationTime(List<Conversation> conversationList) {
        if (CollectionUtils.isEmpty(conversationList)) {
            return;
        }
        Date currentTime = DateUtil.date();
        Date todayEndTime = DateUtil.endOfDay(currentTime);

        RBatch clientBatch = redissonClient.createBatch();
        for (Conversation conversation : conversationList) {
            JSONObject conversationExt = JsonUtil.toObject(conversation.getExt(), JSONObject.class);
            if (conversationExt == null) {
                continue;
            }
            String tenantId = conversationExt.getString("tenantId");
            Long skillSetId = conversationExt.getLong("skillSetId");
            if (StringUtils.isBlank(tenantId) || skillSetId == null) {
                continue;
            }

            Date startTime = DateUtil.parseDateTime(conversation.getStartTime());
            Date endTime = new Date();
            long duration = endTime.getTime() - startTime.getTime();

            String cacheKey = String.format(CacheKeyUtil.CsrRoute.DISTRIBUTION_SKILL_SET_STAT_CONVERSATION_TIME, tenantId);
            RScoredSortedSetAsync<Long> scoredSortedSet = clientBatch.getScoredSortedSet(cacheKey);
            scoredSortedSet.addScoreAsync(skillSetId, duration);
            scoredSortedSet.expireAsync(Duration.ofMillis(todayEndTime.getTime() - currentTime.getTime()));
        }
        clientBatch.executeAsync();
    }

    /**
     * 从指定的技能组集合中，获取会话时长最短的技能组id
     *
     * @param tenantId
     * @param skillSetIdList
     * @return
     */
    public Long getConversationLeastTime(String tenantId, List<Long> skillSetIdList) {
        if (StringUtils.isBlank(tenantId) || CollectionUtils.isEmpty(skillSetIdList)) {
            return null;
        }
        String cacheKey = String.format(CacheKeyUtil.CsrRoute.DISTRIBUTION_SKILL_SET_STAT_CONVERSATION_TIME, tenantId);
        RScoredSortedSet<Long> scoredSortedSet = redissonClient.getScoredSortedSet(cacheKey);

        if (!scoredSortedSet.isExists()) {
            log.info("Cache key does not exist: {}", cacheKey);
            return null;
        }

        // 获取指定元素及其分数
        List<Double> scoreList = scoredSortedSet.getScore(skillSetIdList);

        if (CollectionUtils.isEmpty(scoreList)) {
            log.info("No skill set IDs found for cache key: {}", cacheKey);
            return null;
        }

        // 找到分数最小的元素
        double minScore = Double.MAX_VALUE;
        Long leastTimeSkillSetId = null;

        for (int i = 0; i < skillSetIdList.size(); i++) {
            Long skillSetId = skillSetIdList.get(i);
            Double score = scoreList.get(i);
            if (score != null && score < minScore) {
                minScore = score;
                leastTimeSkillSetId = skillSetId;
            }
        }
        return leastTimeSkillSetId;
    }

    /**
     * 记录每个业务规则每个技能组的会话数量
     *
     * @param tenantId
     * @param skillSetId
     */
    public void increaseConversationCount(String tenantId, Long skillSetId) {
        if (StringUtils.isBlank(tenantId) || skillSetId == null) {
            return;
        }

        Date currentTime = DateUtil.date();
        Date todayEndTime = DateUtil.endOfDay(currentTime);

        String cacheKey = String.format(CacheKeyUtil.CsrRoute.DISTRIBUTION_SKILL_SET_STAT_CONVERSATION_COUNT, tenantId);
        RScoredSortedSet<Long> scoredSortedSet = redissonClient.getScoredSortedSet(cacheKey);
        scoredSortedSet.addScoreAsync(skillSetId, 1);
        scoredSortedSet.expireAsync(Duration.ofMillis(todayEndTime.getTime() - currentTime.getTime()));
    }

    /**
     * 减少技能组的会话数量
     *
     * @param tenantId
     * @param skillSetId
     * @param count
     */
    public void reduceConversationCount(String tenantId, Long skillSetId, int count) {
        if (StringUtils.isBlank(tenantId) || skillSetId == null) {
            return;
        }
        String cacheKey = String.format(CacheKeyUtil.CsrRoute.DISTRIBUTION_SKILL_SET_STAT_CONVERSATION_COUNT, tenantId);
        RScoredSortedSet<Long> scoredSortedSet = redissonClient.getScoredSortedSet(cacheKey);
        if (!scoredSortedSet.isExists()) {
            return;
        }
        scoredSortedSet.addScoreAsync(skillSetId, -count);
    }

    /**
     * 从指定的技能组集合中，获取会话数量最少的技能组id
     *
     * @param tenantId
     * @param skillSetIdList
     * @return
     */
    public Long getConversationLeastCount(String tenantId, List<Long> skillSetIdList) {
        if (StringUtils.isBlank(tenantId) || CollectionUtils.isEmpty(skillSetIdList)) {
            return null;
        }
        String cacheKey = String.format(CacheKeyUtil.CsrRoute.DISTRIBUTION_SKILL_SET_STAT_CONVERSATION_COUNT, tenantId);
        RScoredSortedSet<Long> scoredSortedSet = redissonClient.getScoredSortedSet(cacheKey);

        if (!scoredSortedSet.isExists()) {
            log.info("Cache key does not exist: {}", cacheKey);
            return null;
        }

        // 获取指定元素及其分数
        List<Double> scoreList = scoredSortedSet.getScore(skillSetIdList);

        if (CollectionUtils.isEmpty(scoreList)) {
            log.info("No skill set IDs found for cache key: {}", cacheKey);
            return null;
        }

        // 找到分数最小的元素
        double minScore = Double.MAX_VALUE;
        Long leastTimeSkillSetId = null;

        for (int i = 0; i < skillSetIdList.size(); i++) {
            Long skillSetId = skillSetIdList.get(i);
            Double score = scoreList.get(i);
            if (score != null && score < minScore) {
                minScore = score;
                leastTimeSkillSetId = skillSetId;
            }
        }
        return leastTimeSkillSetId;
    }


}
